home *** CD-ROM | disk | FTP | other *** search
- /* TrackClick.c */
- /*
- * Copyright © 1989 Martin Minow. All rights reserved.
- *
- * You may incorporate portions of this program in your
- * applications without restriction as long as this
- * copyright notice remains intact and the applications
- * are not sold for profit and the source is not
- * redistributed for profit.
- *
- * TrackClick(mouse, extend, track_handle)
- * mouse The mouse location in local coordinates.
- * extend TRUE to extend the selection.
- * track_handle Everything we need to know about the data.
- *
- * Process a mouse button click in the document window.
- *
- * If clikProc is non-NIL, the function will be called
- * repeatedly as follows:
- * (*clikProc)(mouse, TrackPtr)
- * Your function should be declared
- * pascal Boolean
- * myClikLoop(Point mouse, TrackPtr trackptr)
- * where
- * mouse mouse location in window-local coordinates.
- * trackptr pointer to a locked TrackRecord.
- * If the myClikLoop returns FALSE, TrackClick will assume
- * that the mouse button has been released.
- * If clikProc is NIL, TrackClick will autoscroll if the
- * mouse moves outside of the viewRect.
- */
- #include "TrackEdit.h"
- #define TR (*tr)
- #define NIL 0
-
- /*
- * save_select is used for double-clicks to ensure that
- * the TrackRecord has the current selection.
- */
- #define save_select(tr, a, c) do { \
- if (a.start <= c.end) { \
- (tr)->selStart = a.start; \
- (tr)->selEnd = c.end; \
- } \
- else { \
- (tr)->selStart = c.start; \
- (tr)->selEnd = a.end; \
- } \
- } while (0)
-
-
- void
- TrackClick(mouse, shift_click, track_handle)
- Point mouse;
- Boolean shift_click;
- TrackHandle track_handle;
- {
- register TrackPtr tr;
- _Track_state state;
- register DOT dot;
- register Boolean is_word;
- register DOT temp;
- register DOT last_word;
- auto _Track_Loc anchor;
- auto _Track_Loc current;
- DOT last_end, new_end;
- Boolean at_anchor;
-
- tr = _Track_lock(track_handle, &state);
- dot = _Track_mouse_to_dot(tr, mouse);
- is_word = FALSE;
- _Track_caret(tr, _Track_caret_off);
- if (shift_click && TR.selStart != TR.selEnd) {
- /*
- * Extend the selection. If the mouse is outside
- * the current selection, extend from the mouse
- * to the nearest end (the selection always gets
- * bigger). Otherwise, truncate from the start
- * (left). Note: some applications just continue
- * from the current invocation, but I don't think
- * this looks good. Shift-click doesn't do
- * word-by-word (double-click) extension.
- */
- if (dot > TR.selStart)
- _Track_hilite(tr, dot, TR.selEnd);
- else {
- _Track_hilite(tr, dot, TR.selStart);
- TR.selStart = TR.selEnd;
- }
- TR.selEnd = dot;
- }
- else {
- /*
- * Not shift-click with a selection. Dump any
- * previous selection. (_Track_Hilite does nothing
- * if it's called with no selection.)
- */
- _Track_hilite(tr, TR.selStart, TR.selEnd);
- TR.selStart = TR.selEnd = dot;
- /*
- * Check for a double-click. If so, extend the
- * selection to encompass the entire word.
- */
- if ((TickCount() - TR.clickTime) <= GetDblTime()
- && dot == TR.clickLoc) {
- is_word = TRUE;
- _Track_word(tr, mouse, &anchor);
- _Track_hilite(tr, anchor.start, anchor.end);
- current = anchor;
- last_word = anchor.start;
- at_anchor = TRUE;
- }
- }
- /*
- * Track the mouse, extending the visual selection
- * whenever it moves off-character.
- */
- while (WaitMouseUp()) {
- temp = dot;
- do {
- GetMouse(&mouse);
- if (is_word)
- save_select(tr, anchor, current);
- if (TR.clikLoop != NIL
- && !CallPascalB(mouse, tr, TR.clikLoop)) {
- goto done;
- }
- else {
- _Track_autoscroll(tr, &mouse);
- }
- dot = _Track_mouse_to_dot(tr, mouse);
- } while (dot == temp && StillDown());
- if (is_word) {
- /*
- * Word-by-word selection: the mouse moved.
- * Check to see if the mouse is in the same word.
- * If so, do nothing. Else, extend the selection
- * to the new word.
- */
- _Track_word(tr, mouse, ¤t);
- if (current.start != last_word) {
- /*
- * The mouse moved off the current word. The
- * word is always identified by the location of
- * its left end. Invert the selection. If the
- * mouse is before (left of) the current point,
- * invert from the start of the word, else from
- * the end of the word. Note that the word
- * that the user clicked on is not un-hilited.
- */
- last_word = current.start;
- if (current.start < anchor.start) {
- new_end = current.start;
- if (at_anchor)
- last_end = anchor.start;
- else if (last_end > anchor.start) {
- _Track_hilite(tr, last_end, anchor.end);
- last_end = anchor.start;
- }
- }
- else /* if (current.start >= anchor.start) */ {
- new_end = current.end;
- if (at_anchor)
- last_end = anchor.end;
- else if (last_end < anchor.start) {
- _Track_hilite(tr, last_end, anchor.start);
- last_end = anchor.end;
- }
- }
- _Track_hilite(tr, last_end, new_end);
- last_end = new_end;
- at_anchor = (current.start == anchor.start);
- }
- }
- else {
- /*
- * Normal (not word) selection. Just invert from
- * the info->select.end point to the mouse postion.
- */
- _Track_hilite(tr, dot, TR.selEnd);
- TR.selEnd = dot;
- }
- }
- /*
- * Done! remember the mouse location for a subsequent
- * double-click, and normalize the selection (so that
- * info->select.start < info->select.end). If this
- * was a zero-width selection, the user was setting
- * the insertion point, which should be marked.
- */
- done:
- TR.clickTime = TickCount();
- TR.clickLoc = dot;
- if (is_word)
- save_select(tr, anchor, current);
- else if (TR.selStart > TR.selEnd) {
- dot = TR.selStart;
- TR.selStart = TR.selEnd;
- TR.selEnd = dot;
- }
- TR.selRow = _Track_pixel_row(tr, mouse.v);
- _Track_caret(tr, _Track_caret_on);
- _Track_unlock(&state);
- }
-
-